import java.io.Serializable;
import java.util.*;

public class AgenceBancaire implements Serializable {

	private static final long serialVersionUID = 1416817056958762616L;

	private int m_numeroGuichet;
	private String m_adresseAgence;
	private HashMap<Long, CompteCourant> m_comptesCourant;
	private HashMap<Long, CompteEpargne> m_comptesEpargne;
	private HashMap<String, HashMap<Character, HashMap<Long, CompteBancaire>>> m_clients;
	private Banque m_banque;

	public AgenceBancaire (final Banque banque, final String adresse) {

		m_numeroGuichet = banque.numeroRegistreG();
		m_adresseAgence = adresse;
		m_comptesCourant = new HashMap<Long, CompteCourant>();
		m_comptesEpargne = new HashMap<Long, CompteEpargne>();
		m_clients = new HashMap<String, HashMap<Character, HashMap<Long, CompteBancaire>>>();
		m_banque = banque;
	}

	float getSoldeCompte(long l1) {

		if(m_comptesCourant.containsKey(l1)) {

			return m_comptesCourant.get(l1).getSoldeCompte();
		}

		if(m_comptesEpargne.containsKey(l1)) {

			return m_comptesEpargne.get(l1).getSoldeCompte();
		}
		return 0f;
	}

	private final void addEqual(CompteBancaire cB1) {

		if (!m_clients.containsKey(cB1.getTitulaireCompte().toString())) {

			m_clients.put(cB1.getTitulaireCompte().toString(), new HashMap<Character, HashMap<Long, CompteBancaire>>());
		}

		if (cB1.getNumeroCompte() > 8000000 ) {

			if (!m_clients.get(cB1.getTitulaireCompte().toString()).containsKey('C')) {

					m_clients.get(cB1.getTitulaireCompte().toString()).put('C', new HashMap<Long, CompteBancaire>());
			}

			m_comptesCourant.put(((CompteCourant)cB1).getNumeroCompte(), (CompteCourant)cB1);
			m_clients.get(cB1.getTitulaireCompte().toString()).get('C').put(((CompteCourant)cB1).getNumeroCompte(), cB1);
		}
		else {

			if (!m_clients.get(cB1.getTitulaireCompte().toString()).containsKey('E')) {

					m_clients.get(cB1.getTitulaireCompte().toString()).put('E', new HashMap<Long, CompteBancaire>());
			}

			m_comptesEpargne.put(((CompteEpargne)cB1).getNumeroCompte(), (CompteEpargne)cB1);
			m_clients.get(cB1.getTitulaireCompte().toString()).get('E').put(((CompteEpargne)cB1).getNumeroCompte(), cB1);
		}
	}

	public int getNumeroGuichet() {return m_numeroGuichet;}
	public int getNombreComptes() {return getNombreComptesCourant() + getNombreComptesEpargne();}
	public final int getNombreComptesCourant() {return m_comptesCourant.size();}
	public final int getNombreComptesEpargne () {return m_comptesEpargne.size();}

	public final LinkedList<HashMap<?, ?>> getListeComptes() {

		LinkedList<HashMap<?, ?>> l1 = new LinkedList<HashMap<?, ?>>();
		l1.add(0,m_comptesCourant);
		l1.add(1,m_comptesEpargne);
		l1.add(2,m_clients);
		return l1;
	}

	public void addListeComptes(LinkedList<HashMap<?, ?>> l1) {

		m_comptesCourant.putAll(((HashMap<Long, CompteCourant>)l1.get(0)));
		m_comptesEpargne.putAll(((HashMap<Long, CompteEpargne>)l1.get(1)));
		m_clients.putAll((HashMap<String, HashMap<Character, HashMap<Long, CompteBancaire>>>)l1.get(2));
	}

	public void transferer (final AgenceBancaire b) {

		b.addListeComptes(getListeComptes());
		viderComptes();
	}

	public long ouvrirCompte(final Titulaire t1) {

		CompteCourant cC1 = new CompteCourant(m_banque, t1);
		addEqual(cC1);
		return cC1.getNumeroCompte();
	}

	public long ouvrirCompte(final Titulaire t1, float taux) {

		CompteEpargne cE1 = new CompteEpargne(m_banque, t1, taux);
		addEqual(cE1);
		return cE1.getNumeroCompte();
	}

	public void viderComptes() {

		m_clients.clear();
		m_comptesCourant.clear();
		m_comptesEpargne.clear();
	}

	public float executer(long numCompte, char type, String libelle, float montant) {

		float f1 = 0;

		if(numCompte > 8000000) {

			CompteCourant cC1 = m_comptesCourant.get(numCompte);
			f1 = cC1.executer(libelle, type, montant);
			return f1;
		}

		CompteEpargne cE1 = m_comptesEpargne.get(numCompte);
		f1 = cE1.executer(libelle, type, montant);
		return f1;
	}

	public int nombreClients() {

		return m_clients.size();
	}

	public float  totalDepots(char c1) {

		float total = 0;
		Object numC;

		if(c1 == 'C') {

			Iterator<Long> iCc = m_comptesCourant.keySet().iterator();
			while (iCc.hasNext()) {

				numC = iCc.next();
				total += ((CompteCourant)(m_comptesCourant.get((Long)numC))).getSoldeCompte();
			}
		}

		if(c1 == 'E') {

			Iterator<Long> iCe = m_comptesEpargne.keySet().iterator();
			while (iCe.hasNext()) {

				numC = iCe.next();
				total += ((CompteEpargne)(m_comptesEpargne.get((Long)numC))).getSoldeCompte();
			}
		}
		return total;
	}

	public final int nombreOperations(String c1) {

		return calculNbOperation(c1);
	}

	public HashMap<Long, CompteBancaire> getCompteBancaire(final Titulaire t1, char type) {

		if (m_clients.containsKey(t1.toString())) {

			if (m_clients.get(t1.toString()).containsKey(type)) {

				return (m_clients.get(t1.toString()).get(type));
			}
		}
		return new HashMap<Long, CompteBancaire>();
	}

	public final int calculNbOperation(String date2) {

		int nbr = 0;
		Object numC;

		Iterator<Long> iTe= m_comptesEpargne.keySet().iterator();

		while (iTe.hasNext()) {

			 numC = iTe.next();
			 CompteEpargne cE1 = m_comptesEpargne.get((Long)numC);
			 nbr += cE1.getOperationDate(date2);
		}

		Iterator<Long> iTc= m_comptesCourant.keySet().iterator();

		while (iTc.hasNext()) {

			 numC = iTc.next();
			 CompteCourant cC1 = m_comptesCourant.get((Long)numC);
			 nbr += cC1.getOperationDate(date2);
		}
		return nbr;
	}
}
